package org.jflame.context.security.springsecurity;

import org.jflame.commons.util.CollectionHelper;
import org.jflame.context.security.SecurityService;

import java.util.Arrays;
import java.util.Collection;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;

public class SpSecurityService implements SecurityService {

    @Override
    public Object getPrincipal() {
        return SecurityContextHolder.getContext()
                .getAuthentication()
                .getPrincipal();
    }

    @Override
    public boolean hasAuthority(String authority) {
        return hasAnyAuthority(authority);
    }

    @Override
    public boolean hasAnyAuthority(String... authority) {
        Collection<? extends GrantedAuthority> authorities = SecurityContextHolder.getContext()
                .getAuthentication()
                .getAuthorities();
        if (CollectionHelper.isNotEmpty(authorities)) {
            for (GrantedAuthority grantedAuthority : authorities) {
                for (String p : authority) {
                    if (grantedAuthority.getAuthority()
                            .equals(p)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    @Override
    public boolean hasRole(String role) {
        return hasAnyAuthority(roleToAuthority(role));
    }

    @Override
    public boolean hasAnyRole(String... roles) {
        if (roles == null || roles.length == 0) {
            return false;
        }
        String[] roleAuthorities = Arrays.stream(roles)
                .map(this::roleToAuthority)
                .toArray(String[]::new);

        return hasAnyAuthority(roleAuthorities);
    }

    @Override
    public boolean hasAllRoles(Collection<String> roleSet) {
        return roleSet.stream()
                .allMatch(this::hasRole);
    }

    protected String roleToAuthority(String role) {
        return role.startsWith("ROLE_") ? role : "ROLE_" + role;
    }
}
